#!/user/local/bin/python3
from genericpath import isdir
import imghdr
from operator import delitem
import os
from re import search
import re
import string
from sys import path
import sys
from tokenize import String
from typing import List

# 定义颜色常量
NC='\033[0m' # No Color
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
BLUE='\033[34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'


# 获取具名参数的值
import argparse
parser = argparse.ArgumentParser()  # 创建参数解析器
parser.add_argument("-assetDir", "--assetDir", help="The value for argument 'assetDir'")
parser.add_argument("-checkInCodeDir", "--checkInCodeDir", help="The value for argument 'checkInCodeDir'")
parser.add_argument("-codeSuffixsString", "--codeSuffixsString", help="The value for argument 'codeSuffixsString'")
parser.add_argument("-ifUnuseRmoveDirectly", "--ifUnuseRmoveDirectly", help="The value for argument 'ifUnuseRmoveDirectly'")
parser.add_argument("-resultSaveToSheetFilePath", "--resultSaveToSheetFilePath", help="The value for argument 'resultSaveToSheetFilePath'")
args = parser.parse_args()  # 解析命令行参数
assetAbPath = args.assetDir                     #图片所在的资源目录路径
checkAssetInCodeDirPath = args.checkInCodeDir   #项目中dart代码所在目录
codeSuffixsString= args.codeSuffixsString
codeSuffixs=codeSuffixsString.split(",")
ifUnuseRmoveDirectly = False # 如果未使用是否直接本地删除掉该文件，省去手动一个个去删除
sheetFilePath = args.resultSaveToSheetFilePath
# sheetFilePath="APP资源清单表4.xlsx"
if assetAbPath is None:
    print("您要检查的资源文件参数 -assetDir 不能为空，请检查！")
    exit(1) 
if checkAssetInCodeDirPath is None:
    print("您资源文件要在哪个代码目录下检查的参数 -checkAssetInCodeDir 不能为空，请检查！")
    exit(1)
if codeSuffixs is None:
    print("您资源文件要在哪些后缀的代码文件中检查的参数 -codeSuffixs 不能为空，请检查！")
    exit(1)
if sheetFilePath is None:
    print("您检查结果要输出到哪个execl表格的参数 -sheetFilePath 不能为空，请检查！")
    exit(1)
if ifUnuseRmoveDirectly is None:
    ifUnuseRmoveDirectly = False # 如果未使用是否直接本地删除掉该文件，省去手动一个个去删除
print(f"{PURPLE}您将要在代码目录{BLUE} {checkAssetInCodeDirPath} {PURPLE}下排查{BLUE} {assetAbPath} {PURPLE}中的图片是否可能未使用.并将结果保存在{BLUE} {sheetFilePath} {PURPLE}中。{NC}")


def searchImage(filePath:String):
    imageFilePaths = []
    isDir = os.path.isdir(filePath)
    if isDir:
        for f in os.listdir(filePath):
            if f.startswith("."):
                print(f"不检查 {filePath}/{f} 。因为其不是资源文件")
            else:
                tList = searchImage(filePath+"/"+f)
                imageFilePaths.extend(tList)
    else:
        if imghdr.what(filePath) in {"jpg","bmp","jpeg","rgb","tif","png"}:
            imageFilePaths.append(filePath)
    return imageFilePaths

#项目中使用的图片资源路径集合
print("---Analyze unused Assets----")
print(f"{CYAN}----------1.开始查找图片(遍历图片总目录 {assetAbPath} ,返回获取到的图片数组)----------{NC}")
originImageList = searchImage(assetAbPath)
print(f"----------在 {assetAbPath} 文件中找到的所有图片的个数count:" + str(len(originImageList))+"----------")





print(f"{CYAN}----------2.遍历dart文件，获取未使用的图片的路径----------{NC}")
image_using_pathMaps = []
def matchAndDelImage(filePath:String, contentStr:String, filePaths:List):
    #遍历拷贝的list,操作原始的list，list[:]是对原始的一个拷贝
    for imgPath in filePaths[:]:
        #以文件名匹配图片的使用
        # pList = imgPath.split("/")
        # imgName = pList[-1]

        #以使用的文件路径匹配图片
        index = imgPath.find(assetAbPath)
        imgName = imgPath[index+1:]

        match = re.search(imgName, contentStr)
        if match:
            image_using_pathMaps.append({"filePath": filePath, "imagePath": imgPath})
            filePaths.remove(imgPath)

def searchImageInDart(filePath:String,filePaths:List):
    if os.path.isdir(filePath):
        for f in os.listdir(filePath):
            if f == ".DS_Store":
                continue
            searchImageInDart(filePath+"/"+f,filePaths)
    else:
        # 判断文件后缀是否匹配
        is_code_file = any(filePath.endswith(suffix) for suffix in codeSuffixs)
        if is_code_file == False:
            return
        with open(filePath,"r") as f:
            contentStr = f.read()
#            print("contentStr:" + contentStr)
            f.close()
            if len(contentStr) != 0:
                matchAndDelImage(filePath, contentStr, filePaths)

imageList = originImageList[:] # 深拷贝 deep copy
searchImageInDart(checkAssetInCodeDirPath, imageList) # 内部会对传进去的 imageList 进行删除操作，以提高检索效率，所以要先deep copy


def get_FileSize(filePath):
    fsize = os.path.getsize(filePath)
    fsize = fsize/float(1024)
    return round(fsize, 2)

imageUsingPaths = []
image_using = []
image_unuse = []

def getMatchMap(imgPath:String, imageUsingPathMaps:List):
    matchIndex = -1
    # 方法1:
#    for matchImagePathMap in imageUsingPathMaps:
#        matchImagePath = matchImagePathMap["imagePath"]
#        imageUsingPaths.append(matchImagePath)
#    matchIndex = imageUsingPaths.index(imgPath)
#    isMatch = imgPath in imageUsingPaths
#    return matchIndex
    # 方法2:
    matchCount = len(imageUsingPathMaps)
    for i in range(0, matchCount, 1):
        matchImagePathMap = imageUsingPathMaps[i]
        matchImagePath = matchImagePathMap["imagePath"]
        match = re.search(imgPath, matchImagePath)
        if match:
            matchIndex = i
            break
    
    if matchIndex >= 0:
        imageUsingPathMap = imageUsingPathMaps[matchIndex]
        return {
            "imagePath": imageUsingPathMap["imagePath"],
            "filePath": imageUsingPathMap["filePath"],
            "matchIndex": matchIndex,
        }
    else:
        return None
    

def printImages(originList:List, imageUsingPathMaps:List):
    for imgPath in originList:
        size = get_FileSize(imgPath)
        kbSize="%.2fKB"%(size)
        
        matchMap = getMatchMap(imgPath, imageUsingPathMaps)
        if not matchMap is None:
            useInFilePath = matchMap["filePath"]
            image_using.append({"path": imgPath, "kbSize": size, "isUse": "using", "useInFile": useInFilePath})
            print("using-->" + imgPath + kbSize)
        else:
            image_unuse.append({"path": imgPath, "kbSize": size, "isUse": "unused"})
            print("may be unused-->" + imgPath + kbSize)



copyImageList = originImageList[:]
printImages(copyImageList, image_using_pathMaps)

print(f"------在dart文件中未找到被使用的图片个数count: {str(len(image_unuse))}/{str(len(originImageList))}")
#for img in image_using_path:
#    print("may be unused-->" + img)

#for imageMap in image_using:
#    print("using-->" + imageMap["path"])
#
#for imageMap in image_unuse:
#    print("may be unused-->" + imageMap["path"] + imageMap["size"])
#    os.remove(imageMap["path"])
print(f"{GREEN}分析完成，正写入到excel中...{NC}")




#!/user/local/bin/python3
#将本文件放在Flutter项目的根目录

import sys
import os
import xlsxwriter # 使用如下命令安装: pip3 install xlsxwriter


#import xlsxwriter
# create a new Excel file and add a worksheet
# 创建工作薄 workbook('demo.xlsx')
# sheetFilePath="APP资源清单表4.xlsx"
# sheetFilePath=data["unuse_output"]["imageSheetFileName"]
workbook = xlsxwriter.Workbook(sheetFilePath)
# 创建工作表
worksheet = workbook.add_worksheet()
# Widen the first column to make the text clearer
# 设置一列或者多列单元属性
worksheet.set_column('A:A',20) #设定A列列宽为40
# Add a bold format to use to highlight cells
# 在工作表中创建一个新的格式对象来格式化单元格，实现加粗
bold = workbook.add_format({'bold': True})
# write some simple text.
# 工总表写入简单文本
worksheet.write('A1', 'hello')
# Text with formatting
# 工作表写入带有格式的文本，加粗
worksheet.write('A2', 'World', bold)
# Write some numbers, with row/column notation #按照坐标写入
worksheet.write(2, 0, 1235)
worksheet.write(3, 0, 123.456)



#[xlsxwriter模块add_format参数详解](https://blog.csdn.net/u013151699/article/details/122594187?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-122594187-blog-64443938.pc_relevant_aa_2&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-122594187-blog-64443938.pc_relevant_aa_2&utm_relevant_index=1)
titleRowIndex=0
worksheet.set_row(0, 30.0) # set_row(row, height)方法，用于设定某一行单元格的行高
titleFontFormat = {
    'bold': True,  # 字体加粗
    'align': 'center',  # 水平位置设置：居中
    'valign': 'vcenter',  # 垂直位置设置，居中
    'font_size': 20,  # '字体大小设置'
}
#worksheet.write(titleRowIndex, 0, "APP资源清单表", workbook.add_format(titleFontFormat))
worksheet.merge_range('A1:F1', "APP资源清单表", workbook.add_format(titleFontFormat))
nextRowIndex = 1

propertyRowIndex=nextRowIndex
worksheet.set_row(1, 20.0) # set_row(row, height)方法，用于设定某一行单元格的行高
propertyFont = workbook.add_format({'bold': True, 'font_size': 12})
#set_column(first_col, last_col, width)方法，用于设置一列或多列单元格的列宽

worksheet.write(propertyRowIndex, 0, "path 资源文件名(含目录)", propertyFont)
worksheet.set_column(0, 0, 100)

worksheet.write(propertyRowIndex, 1, "size(kb)", propertyFont)
worksheet.set_column(1, 1, 10)

worksheet.write(propertyRowIndex, 2, "isUse 是否使用中", propertyFont)
worksheet.set_column(2, 2, 20)

worksheet.write(propertyRowIndex, 3, "图片", propertyFont)
imageShowWidth=20.0
worksheet.set_column(3, 3, imageShowWidth)

worksheet.write(propertyRowIndex, 4, "width")
worksheet.write(propertyRowIndex, 5, "height")
worksheet.write(propertyRowIndex, 6, "useInFile")
worksheet.set_column(6, 6, 100)


nextRowIndex += 1




try:
    from PIL import Image # 这里要用 python3.9 ，否则使用 python3 会错误
except ImportError:
    print(f"{RED}Image 无法使用，这里要用 python3.9 ，否则使用 python3 会错误 {RED}。{NC}")
    exit(1)
unuseCount = len(image_unuse)
print(f"----------------可能未使用的图片有{unuseCount}个，分别如下----------------")
#for imageMap in image_unuse:
for i in range(0, unuseCount, 1):
    imageMap = image_unuse[i]
#    print("may be unused-->" + "%d:"%(i) + imageMap["path"] + ", " + "%.2fKB"%(imageMap["kbSize"]))

    currentRowIndex = nextRowIndex+i
    worksheet.write(currentRowIndex, 0, imageMap["path"])
    worksheet.write(currentRowIndex, 1, imageMap["kbSize"])
    worksheet.write(currentRowIndex, 2, imageMap["isUse"])

    img = Image.open(imageMap["path"])
    scale = (imageShowWidth*3)/img.width
    print("may be unused-->" + "%d:"%(i) + imageMap["path"] + ", " + "%.2fKB"%(imageMap["kbSize"]) + ", " + "imageShowWidth:%.2f"%(imageShowWidth) + ", %.2f"%(img.width) + ", %.2f"%(img.height))
    imageShowHeight = scale*img.height
    worksheet.set_row(currentRowIndex, imageShowHeight) # set_row(row, height)方法，用于设定某一行单元格的行高
    worksheet.insert_image(currentRowIndex, 3, imageMap["path"], {'x_scale': scale, 'y_scale': scale})
    worksheet.write(currentRowIndex, 4, img.width)
    worksheet.write(currentRowIndex, 5, img.height)
    
            
for i in range(0, unuseCount, 1):
    imageMap = image_unuse[i]
    if ifUnuseRmoveDirectly:
        if os.path.exists(imageMap["path"]):
            os.remove(imageMap["path"]) # 直接删除本地的图片


nextRowIndex += unuseCount

usingCount = len(image_using)
print(f"----------------使用中的图片有{usingCount}个，分别如下----------------")
#for imageMap in image_using:
for i in range(0, usingCount, 1):
    imageMap = image_using[i]
    print("using-->" + "%d:"%(i) + imageMap["path"] + ", " + "%.2fKB"%(imageMap["kbSize"]))
    currentRowIndex = nextRowIndex+i

    if imageMap["kbSize"] > 1000 :
        resourceSizeFont = workbook.add_format({'bg_color': 'red', 'font_size': 12})
    elif imageMap["kbSize"] > 500 :
        resourceSizeFont = workbook.add_format({'bg_color': 'orange', 'font_size': 12})
    else:
        resourceSizeFont = workbook.add_format({'font_size': 12})
    worksheet.write(currentRowIndex, 0, imageMap["path"])
    worksheet.write(currentRowIndex, 1, imageMap["kbSize"], resourceSizeFont)
    worksheet.write(currentRowIndex, 2, imageMap["isUse"])
    worksheet.write(currentRowIndex, 6, imageMap["useInFile"])

# Insert an image.
# 插入图片
#worksheet.insert_image('B5', 'lena.png')
# 关闭工作薄
workbook.close()


import os
print(f"{GREEN}恭喜{BLUE} {sheetFilePath} {GREEN}已生成，并为你自动打开. {NC}")

import subprocess
# 在 macOS 或 Linux 上打开 file_path 文件。
subprocess.Popen(['open', sheetFilePath])